package com.yike.websocket.filter;

import com.yike.websocket.redis.RedisUtil;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author Sakura
 * @date 2024/9/26 10:22
 */
@WebFilter(filterName = "websocketAuthFilter", urlPatterns = "/chat/*")
@Component
@Log4j2
public class WebSocketAuthFilter implements Filter {

    @Autowired
    RedisUtil redisUtil;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;

        String url = httpRequest.getRequestURI();
        //log.info("请求路径：" + url);
        // @Component注解会导致urlPatterns失效，所以在此处理一下
        if (url.startsWith("/chat/")) {
            String accessToken = httpRequest.getParameter("Access-Token"); // 通过查询参数获取
            log.info("token：" + accessToken);

            if (!isValidToken(accessToken, url.replace("/chat/", ""))) {
                // 如果无效，返回 401 或 403 状态码
                ((HttpServletResponse) response).sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
                return;
            }
        }

        chain.doFilter(request, response); // 继续执行过滤链
    }

    private boolean isValidToken(String accessToken, String userId) {
        if (accessToken != null && redisUtil.hasKey(accessToken)) {
            // 如果存在token则还需要校验当前token和用户ID是否一致
            String token = (String) redisUtil.get("ws_" + userId);
            //log.info("redis token：" + accessToken);
            if (token != null && token.equals(accessToken)) {
                // 此处刷新一下token
                redisUtil.set("ws_" + userId, token, 30 * 24 * 60 * 60);
                return true;
            }
        }
        return false;
    }

}

